package org.yaac.server.egql.evaluator.function;

import java.io.Serializable;
import java.math.BigDecimal;

import org.yaac.server.egql.evaluator.EvaluationResult;
import org.yaac.server.egql.exception.EGQLException;
import org.yaac.server.egql.processor.ProcessData.ProcessDataRecord;
import org.yaac.shared.ErrorCode;
import org.yaac.shared.file.FileDownloadPath;

/**
 * @author Max Zhu (thebbsky@gmail.com)
 *
 */
public class TextFunction extends Function {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	public static class TextStringWrapper implements Serializable {

		/**
		 * 
		 */
		private static final long serialVersionUID = 1L;
		
		private String rawString;

		/**
		 * 
		 */
		@SuppressWarnings("unused")
		private TextStringWrapper() {
			super();
		}
		
		public TextStringWrapper(String rawString) {
			super();
			this.rawString = rawString;
		}
		
		public String getRawString() {
			return rawString;
		}

		@Override
		public int hashCode() {
			final int prime = 31;
			int result = 1;
			result = prime * result + ((rawString == null) ? 0 : rawString.hashCode());
			return result;
		}

		@Override
		public boolean equals(Object obj) {
			if (this == obj)
				return true;
			if (obj == null)
				return false;
			if (getClass() != obj.getClass())
				return false;
			TextStringWrapper other = (TextStringWrapper) obj;
			if (rawString == null) {
				if (other.rawString != null)
					return false;
			} else if (!rawString.equals(other.rawString))
				return false;
			return true;
		}

		@Override
		public String toString() {
			return "TextStringWrapper [rawString=" + rawString + "]";
		}
	}
	
	public static class TextFileRefWrapper implements Serializable {
		/**
		 * 
		 */
		private static final long serialVersionUID = 1L;
		
		private FileDownloadPath ref;

		/**
		 * 
		 */
		@SuppressWarnings("unused")
		private TextFileRefWrapper(){}
		
		/**
		 * @param ref
		 */
		public TextFileRefWrapper(FileDownloadPath ref) {
			super();
			this.ref = ref;
		}
		
		public FileDownloadPath getRef() {
			return ref;
		}

		@Override
		public int hashCode() {
			final int prime = 31;
			int result = 1;
			result = prime * result + ((ref == null) ? 0 : ref.hashCode());
			return result;
		}

		@Override
		public boolean equals(Object obj) {
			if (this == obj)
				return true;
			if (obj == null)
				return false;
			if (getClass() != obj.getClass())
				return false;
			TextFileRefWrapper other = (TextFileRefWrapper) obj;
			if (ref == null) {
				if (other.ref != null)
					return false;
			} else if (!ref.equals(other.ref))
				return false;
			return true;
		}

		@Override
		public String toString() {
			return "TextFileRefWrapper [ref=" + ref + "]";
		}
	}
	
	
	@Override
	public void validate() throws EGQLException {
		FunctionUtil.ensureParamSize(ops, 1);
	}

	@Override
	public EvaluationResult evaluate(ProcessDataRecord record) {
		EvaluationResult r = ops.get(0).evaluate(record);
		
		// since this will only be used when user is trying to execute an expression with function text
		// then the actual text will NEVER be passed in as ops.get(0).evaluate(context).getPayload()
		if (r.getPayload() instanceof String) {
			return new EvaluationResult(new TextStringWrapper((String) r.getPayload()), r);	
		} else if (r.getPayload() instanceof BigDecimal) {
			BigDecimal bd = (BigDecimal) r.getPayload();
			int index = bd.intValue() - 1;
			return new EvaluationResult(new TextFileRefWrapper(record.lookupFileReference(index)));
		} else {
			return r.withWarning(ErrorCode.W132);
		}
	}
}
